package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.dao.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.*;
import com.sc.nft.exception.GlobalException;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.DaoService;
import com.sc.nft.service.UserCityServerCentreService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service
public class DaoServiceImpl implements DaoService {

    private final UserInfoDao userInfoDao;

    private final OrderDao orderDao;

    private final DaoLevelDao daoLevelDao;

    private final UserCollectionDao userCollectionDao;

    private final DigitalCollectionDao digitalCollectionDao;

    private final StaticDataDao staticDataDao;

    private final UserWalletDao userWalletDao;

    private final UserIncomeRecordDao userIncomeRecordDao;
    private final UserChainInfoDao userChainInfoDao;

    private final UserCityServerCentreService userCityServerCentreService;

    /**
     * 判断用户是否升级
     * 升级入口 添加藏品
     * 1.购买(杉德回调,钱包购买)
     * 2.合成
     * 3.兑换
     * 4.空投
     * 5.寄售
     *
     * @param collectionId
     * @param userId
     */
    @Override
    public void upgrade(Long collectionId, Long userId, ReceivedCollectionType type) {
        //查询藏品信息
        DigitalCollection collection = digitalCollectionDao.getById(collectionId);
        //判断是否是升级的藏品
        if (collection.getIsUpgrade()) {
            //获取用户信息
            UserInfo user = userInfoDao.getById(userId);
            //如果是城主卡
            if (collection.getDaoLevel() == DaoLevelTypeEnum.CITY_LORD) {
                //判断当前用户等级 小于城主的等级
                if (collection.getDaoLevel().getCode() == DaoLevelTypeEnum.CITY_LORD.getCode() && user.getLevel().getCode() < DaoLevelTypeEnum.CITY_LORD.getCode()) {
                    log.info("执行升级城主");
                    //该用户升级成城主
                    userInfoDao.updateUserLevel(DaoLevelTypeEnum.CITY_LORD, user.getId());
                    //升级日志记录
                    DaoLevelLog daoLevelLog = new DaoLevelLog();
                    daoLevelLog.setUserId(user.getId());
                    daoLevelLog.setBeforeDaoLevel(user.getLevel());
                    daoLevelLog.setCollectionUuid(collection.getDigitalCollectionUuid());
                    daoLevelLog.setReceivedCollectionType(type);
                    daoLevelLog.setAfterDaoLevel(DaoLevelTypeEnum.CITY_LORD);
                    daoLevelLog.setIsUpgrade(Boolean.TRUE);
                    daoLevelLog.insert();
                }
            } else if (collection.getDaoLevel().getCode() == DaoLevelTypeEnum.RESIDENT.getCode() && user.getLevel().getCode() < DaoLevelTypeEnum.RESIDENT.getCode()) {
                //该用户升级成居民
                log.info("执行升级居民");
                userInfoDao.updateUserLevel(DaoLevelTypeEnum.RESIDENT, user.getId());
                //升级日志记录
                DaoLevelLog daoLevelLog = new DaoLevelLog();
                daoLevelLog.setUserId(user.getId());
                daoLevelLog.setBeforeDaoLevel(user.getLevel());
                daoLevelLog.setCollectionUuid(collection.getDigitalCollectionUuid());
                daoLevelLog.setReceivedCollectionType(type);
                daoLevelLog.setAfterDaoLevel(DaoLevelTypeEnum.RESIDENT);
                daoLevelLog.setIsUpgrade(Boolean.TRUE);
                daoLevelLog.insert();
            }
        }
    }

    /**
     * 判断用户是否降级
     * 城主降级: 城主 -> 居民 -> 游客
     * 居民降级: 居民 -> 游客
     * 入口 :
     * 1.转增 : 1.判断当前用户是否持有同等级的卡,如果没有则降级  2.判断当前用户是否持有下一等级的卡,如果没有则降级
     * 2.寄售 : 上架就降级? 卖出再降级? 待定
     *
     * @param collectionId
     * @param userId
     */
    @Override
    public void downgrade(Long collectionId, Long userId, ReceivedCollectionType type) {
        //查询藏品信息
        DigitalCollection collection = digitalCollectionDao.getById(collectionId);
        //判断是否是升级的藏品
        if (collection.getIsUpgrade()) {
            //获取用户信息
            UserInfo user = userInfoDao.getById(userId);
            //如果交易的是城主卡
            if (collection.getDaoLevel() == DaoLevelTypeEnum.CITY_LORD) {
                //查询当前用户持有的成主卡
                Integer cityLordCount = userCollectionDao.getCountByCollercitonIdAndUserId(user.getId(), collectionId);
                //如果没有持有的城主卡 则降级
                if (cityLordCount == 0) {
                    String residentCollectionId = staticDataDao.getByType("resident_collection_id").getValue();
                    //查询居民卡持有数量
                    Integer residentCount = userCollectionDao.getCountByCollercitonIdAndUserId(user.getId(), Long.valueOf(residentCollectionId));
                    Integer secondResidentCount = userCollectionDao.getCountByCollercitonIdAndUserId(user.getId(), 489L);
                    //如果没有持有居民卡 则降级成游客
                    if (residentCount == 0 && secondResidentCount == 0) {
                        //降级成游客
                        userInfoDao.updateUserLevel(DaoLevelTypeEnum.TOURISTS, user.getId());
                        //记录日志
                        DaoLevelLog daoLevelLog = new DaoLevelLog();
                        daoLevelLog.setUserId(user.getId());
                        daoLevelLog.setBeforeDaoLevel(user.getLevel());
                        daoLevelLog.setCollectionUuid(collection.getDigitalCollectionUuid());
                        daoLevelLog.setReceivedCollectionType(type);
                        daoLevelLog.setAfterDaoLevel(DaoLevelTypeEnum.TOURISTS);
                        daoLevelLog.setIsUpgrade(Boolean.FALSE);
                        daoLevelLog.insert();
                    } else {
                        //降级成居民
                        userInfoDao.updateUserLevel(DaoLevelTypeEnum.RESIDENT, user.getId());
                        //记录日志
                        DaoLevelLog daoLevelLog = new DaoLevelLog();
                        daoLevelLog.setUserId(user.getId());
                        daoLevelLog.setBeforeDaoLevel(user.getLevel());
                        daoLevelLog.setCollectionUuid(collection.getDigitalCollectionUuid());
                        daoLevelLog.setReceivedCollectionType(type);
                        daoLevelLog.setAfterDaoLevel(DaoLevelTypeEnum.RESIDENT);
                        daoLevelLog.setIsUpgrade(Boolean.FALSE);
                        daoLevelLog.insert();
                    }
                }
            } else if (collection.getDaoLevel() == DaoLevelTypeEnum.RESIDENT) {

                if (user.getLevel() == DaoLevelTypeEnum.RESIDENT) {
                    //查询居民卡持有数量
                    String residentCollectionId = staticDataDao.getByType("resident_collection_id").getValue();
                    Integer residentCount = userCollectionDao.getCountByCollercitonIdAndUserId(user.getId(), Long.valueOf(residentCollectionId));
                    Integer secondResidentCount = userCollectionDao.getCountByCollercitonIdAndUserId(user.getId(), 489L);
                    if (residentCount == 0 && secondResidentCount == 0) {
                        //降级成游客
                        userInfoDao.updateUserLevel(DaoLevelTypeEnum.TOURISTS, user.getId());
                        //记录日志
                        DaoLevelLog daoLevelLog = new DaoLevelLog();
                        daoLevelLog.setUserId(user.getId());
                        daoLevelLog.setBeforeDaoLevel(user.getLevel());
                        daoLevelLog.setCollectionUuid(collection.getDigitalCollectionUuid());
                        daoLevelLog.setReceivedCollectionType(type);
                        daoLevelLog.setAfterDaoLevel(DaoLevelTypeEnum.TOURISTS);
                        daoLevelLog.setIsUpgrade(Boolean.FALSE);
                        daoLevelLog.insert();
                    }
                }
            }
        }
    }

    @Override
    public UserDaoVO getUserDaoDetails(UserInfo user) {

        //拷贝用户基础信息
        UserDaoVO userDaoVO = BeanUtil.copyProperties(user, UserDaoVO.class);
        userDaoVO.setInviteNum(userInfoDao.getCountRecommendUserId(user.getId()));

        //一级交易金额
        BigDecimal teamHoldToken = userInfoDao.getSumHoldTokenByRecommendId(user.getId());
        //二级交易金额
        BigDecimal teamSecondaryHoldToken = userInfoDao.getSumSecondaryHoldTokenByRecommendId(user.getId());

//        //获取区块链地址
        UserChainInfo chainInfo = userChainInfoDao.getRegisterByUserId(user.getId());
        if (ObjectUtil.isNotNull(chainInfo)) {
            //设置区块链地址
            userDaoVO.setNftAddr(chainInfo.getAddress());
        } else {
            userDaoVO.setNftAddr("待生成");
        }

        //设置一级交易金额
        userDaoVO.setTeamHoldToken(teamHoldToken.stripTrailingZeros().toPlainString());
        //设置二级交易金额
        userDaoVO.setTeamSecondaryHoldToken(teamSecondaryHoldToken.stripTrailingZeros().toPlainString());

        //二维码邀请链接
        StaticData staticData = staticDataDao.getByType("share_url");
        userDaoVO.setShareUrl(staticData.getValue() + user.getInviteCode());

        //跳转到H5的链接
        StaticData webUrl = staticDataDao.getByType("web_url");
        userDaoVO.setWebUrl(webUrl.getValue());
        // 用户城市服务中心数据
        UserCityServerCentre userCityServerCentre = userCityServerCentreService.selectByUserId(user.getId());
        userDaoVO.setUserCityServerCentre(userCityServerCentre);
        return userDaoVO;
    }

    @Override
    public Page getRecommendListByUser(Long userId, String time, String holdToken, String secondaryHoldToken, Integer pageNo, Integer pageSize) {
        Page<UserInfo> recommendListByUserIdQueryConditions = userInfoDao.getRecommendListByUserIdQueryConditions(userId, time, holdToken, secondaryHoldToken, pageNo, pageSize);
        List<UserInfo> records = recommendListByUserIdQueryConditions.getRecords();
        List<UserInfo> objectArrayList = Lists.newArrayList();
        for (UserInfo record : records) {
            String userTel = record.getUserTel();
            record.setUserTel(DesensitizedUtil.mobilePhone(userTel));
            record.setHoldToken(record.getHoldToken().stripTrailingZeros());
            record.setSecondaryHoldToken(record.getSecondaryHoldToken().stripTrailingZeros());
            objectArrayList.add(record);
        }
        recommendListByUserIdQueryConditions.setRecords(objectArrayList);
        return recommendListByUserIdQueryConditions;
    }

    @Override
    public UserDaoVO getUserDaoDetailsByH5(Long userId) {
        UserInfo user;
        if (ObjectUtil.isNotEmpty(userId) && userId.intValue() != 0) {
            user = userInfoDao.getById(userId);
        } else {
            user = UserPool.getUser();
        }
        //拷贝对象
        UserDaoVO userDaoVO = BeanUtil.copyProperties(user, UserDaoVO.class);
        //        //获取区块链地址
        UserChainInfo chainInfo = userChainInfoDao.getRegisterByUserId(user.getId());
        if (ObjectUtil.isNotNull(chainInfo)) {
            //设置区块链地址
            userDaoVO.setNftAddr(chainInfo.getAddress());
        } else {
            userDaoVO.setNftAddr("待生成");
        }
        //首发交易(直推总额)
        BigDecimal teamHoldToken = userInfoDao.getSumHoldTokenByRecommendId(user.getId());
        //二级交易(直推总额)
        BigDecimal teamSecondaryHoldToken = userInfoDao.getSumSecondaryHoldTokenByRecommendId(user.getId());

        //二维码邀请链接
        StaticData staticData = staticDataDao.getByType("share_url");
        userDaoVO.setShareUrl(staticData.getValue() + user.getInviteCode());

        userDaoVO.setTeamHoldToken(teamHoldToken.stripTrailingZeros().toPlainString());
        userDaoVO.setTeamSecondaryHoldToken(teamSecondaryHoldToken.stripTrailingZeros().toPlainString());
        // 用户城市服务中心数据
        UserCityServerCentre userCityServerCentre = userCityServerCentreService.selectByUserId(user.getId());
        userDaoVO.setUserCityServerCentre(userCityServerCentre);
        return userDaoVO;
    }

    @Override
    public Page getRecommendListByUserH5(Long userId, String time, String holdToken, String secondaryHoldToken, Integer pageNo, Integer pageSize) {
        UserInfo user;
        if (ObjectUtil.isNotEmpty(userId) && userId.intValue() != 0) {
            user = userInfoDao.getById(userId);
        } else {
            user = UserPool.getUser();
        }
        return getRecommendListByUser(user.getId(), time, holdToken, secondaryHoldToken, pageNo, pageSize);
    }

    @Override
    public GetIncomeDetailsVO getIncomeDetails() {
        UserInfo user = UserPool.getUser();
        GetIncomeDetailsVO getIncomeDetailsVO = BeanUtil.copyProperties(user, GetIncomeDetailsVO.class);

        //查询用户钱包
        UserWallet userWallet = userWalletDao.getByUserId(user.getId());
        //总收益
        BigDecimal sumIncome = userWallet.getSumIncome();

        //        //获取区块链地址
        UserChainInfo chainInfo = userChainInfoDao.getRegisterByUserId(user.getId());
        if (ObjectUtil.isNotNull(chainInfo)) {
            //设置区块链地址
            getIncomeDetailsVO.setNftAddr(chainInfo.getAddress());
        } else {
            getIncomeDetailsVO.setNftAddr("待生成");
        }
        //获取昨日收益
        BigDecimal yesterdayIncome = userIncomeRecordDao.findSumAmountByUserIdAndYesterDay(user.getId());
        ArrayList<JSONObject> list = Lists.newArrayList();
        IncomeHierarchyEnum[] values = IncomeHierarchyEnum.values();
        for (IncomeHierarchyEnum value : values) {
            JSONObject json = new JSONObject();
            json.put("name", value.getDescription());
            json.put("type", value.toString());
            list.add(json);
        }
        getIncomeDetailsVO.setSumIncome(sumIncome.stripTrailingZeros().toPlainString());
        getIncomeDetailsVO.setYesterdayIncome(yesterdayIncome.stripTrailingZeros().toPlainString());
        getIncomeDetailsVO.setList(list);
        return getIncomeDetailsVO;
    }

    @Override
    public GetIncomeDetailsVO getIncomeNewDetails() {
        UserInfo user = UserPool.getUser();
        GetIncomeDetailsVO getIncomeDetailsVO = BeanUtil.copyProperties(user, GetIncomeDetailsVO.class);

        //查询用户钱包
        UserWallet userWallet = userWalletDao.getByUserId(user.getId());
        //总收益
        BigDecimal sumIncome = userWallet.getSumIncome();

        //        //获取区块链地址
        UserChainInfo chainInfo = userChainInfoDao.getRegisterByUserId(user.getId());
        if (ObjectUtil.isNotNull(chainInfo)) {
            //设置区块链地址
            getIncomeDetailsVO.setNftAddr(chainInfo.getAddress());
        } else {
            getIncomeDetailsVO.setNftAddr("待生成");
        }
        //获取昨日收益
        BigDecimal yesterdayIncome = userIncomeRecordDao.findSumAmountByUserIdAndYesterDay(user.getId());
        ArrayList<JSONObject> list = Lists.newArrayList();
        IncomeHierarchyListEnum[] values = IncomeHierarchyListEnum.values();
        for (IncomeHierarchyListEnum value : values) {
            JSONObject json = new JSONObject();
            json.put("name", value.getDescription());
            json.put("type", value.getIncomeHierarchyEnum());
            list.add(json);
        }
        getIncomeDetailsVO.setSumIncome(sumIncome.stripTrailingZeros().toPlainString());
        getIncomeDetailsVO.setYesterdayIncome(yesterdayIncome.stripTrailingZeros().toPlainString());
        getIncomeDetailsVO.setList(list);
        return getIncomeDetailsVO;
    }

    @Override
    public Page<IncomeDetailsVO> getIncomeListNewVersions(List<IncomeHierarchyEnum> incomeHierarchyEnum, Integer pageNo, Integer pageSize) {
        return userIncomeRecordDao.findListByHierarchyAndUserIdNewVesion(incomeHierarchyEnum.stream().map(IncomeHierarchyEnum::getCode).collect(Collectors.toList()), UserPool.getUser().getId(), pageNo, pageSize);
    }

    @Override
    public Page<IncomeDetailsVO> getIncomeList(IncomeHierarchyEnum incomeHierarchyEnum, Integer pageNo, Integer pageSize) {
        return userIncomeRecordDao.findListByHierarchyAndUserId(incomeHierarchyEnum.getCode(), UserPool.getUser().getId(), pageNo, pageSize);
    }

    @Override
    public Page<UserIncomeDetailsVO> pageIncomeList(Integer incomeTypeEnum, String userTel, Date startDate, Date endDate, Integer pageNo, Integer pageSize) throws GlobalException {
        Long userId = null;
        if (StrUtil.isNotBlank(userTel)) {
            UserInfo userInfo = userInfoDao.getOneByUserTel(userTel);
            if (ObjectUtil.isNull(userInfo)) {
                throw new GlobalException("用户不存在");
            }
            userId = userInfo.getId();
        }

        return userIncomeRecordDao.pageIncomeList(incomeTypeEnum, userId, startDate, endDate, pageNo, pageSize);
    }

    @Override
    public DaoLevelVO getDaoLevelList() {
        //获取用户信息
        UserInfo user = UserPool.getUser();
        Boolean residentIsActivation = Boolean.FALSE;
        Boolean cityLordIsActivation = Boolean.FALSE;
        Integer isShow = 0;
        //如果是城主的等级 两个等级都是激活状态
        if (user.getLevel() == DaoLevelTypeEnum.CITY_LORD) {
            cityLordIsActivation = Boolean.TRUE;
            isShow = 2;
        } else if (user.getLevel() == DaoLevelTypeEnum.RESIDENT) {
            //如果是居民的等级  居民是激活状态
            residentIsActivation = Boolean.TRUE;
            isShow = 1;
        } else if (user.getLevel() == DaoLevelTypeEnum.TOURISTS) {
            isShow = 0;
        }
        //居民卡藏品id
        String residentCollectionId = staticDataDao.getByType("resident_collection_id").getValue();
        //城主卡藏品id
        String cityLordCollectionId = staticDataDao.getByType("city_lord_collection_id").getValue();
        //居民卡商品id
        String residentProductId = staticDataDao.getByType("resident_product_id").getValue();
        //城主卡商品id
        String cityLordProductId = staticDataDao.getByType("city_lord_product_id").getValue();
        //持有居民卡片
        Integer residentCount = userCollectionDao.getCountByCollercitonIdAndUserId(Long.valueOf(residentCollectionId), user.getId());
        //持有城主卡片
        Integer cityLordCount = userCollectionDao.getCountByCollercitonIdAndUserId(Long.valueOf(cityLordCollectionId), user.getId());
        // 用户服务中心数据.
        UserCityServerCentre userCityServerCentre = userCityServerCentreService.selectByUserId(user.getId());

        //拷贝基础信息
        DaoLevelVO daoLevelVO = BeanUtil.copyProperties(user, DaoLevelVO.class);
        daoLevelVO.setUserCityServerCentre(userCityServerCentre);
        //todo 换链之后再更新
        daoLevelVO.setNftAddr("待生成");
        //初始化等级列表信息
        ArrayList<DaoLevelDetailsVO> daoLevelDetailsList = Lists.newArrayList();
        //获取数据库的等级信息
        List<DaoLevel> list = daoLevelDao.list();
        for (DaoLevel daoLevel : list) {
            //拷贝每个等级的基础信息
            DaoLevelDetailsVO daoLevelDetailsVO = BeanUtil.copyProperties(daoLevel, DaoLevelDetailsVO.class);
            //如果等级是居民  就赋值居民商品id
            if (daoLevel.getDaoLevel() == DaoLevelTypeEnum.RESIDENT) {
                //设置居民商品id
                daoLevelDetailsVO.setProductId(Long.valueOf(residentProductId));
                //设置居民激活状态
                daoLevelDetailsVO.setIsActivation(residentIsActivation);
                //设置居民卡藏品的持有数量
                daoLevelDetailsVO.setHoldCount(residentCount);
                String value = staticDataDao.getByType("resident_img").getValue();
                daoLevelDetailsVO.setImg(value);
                //如果等级是领主  就赋值领主商品id
            } else if (daoLevel.getDaoLevel() == DaoLevelTypeEnum.CITY_LORD) {
                //设置城主商品id
                daoLevelDetailsVO.setProductId(Long.valueOf(cityLordProductId));
                //设置城主激活状态
                daoLevelDetailsVO.setIsActivation(cityLordIsActivation);
                //设置城主卡藏品持有数量
                daoLevelDetailsVO.setHoldCount(cityLordCount);
                String value = staticDataDao.getByType("city_lord_img").getValue();
                daoLevelDetailsVO.setImg(value);

            }
            daoLevelDetailsList.add(daoLevelDetailsVO);
        }
        daoLevelVO.setIsShow(isShow);

        //        //获取区块链地址
        UserChainInfo chainInfo = userChainInfoDao.getRegisterByUserId(user.getId());
//        //设置区块链地址
        if (ObjectUtil.isNotNull(chainInfo)) {
            //设置区块链地址
            daoLevelVO.setNftAddr(chainInfo.getAddress());
        } else {
            daoLevelVO.setNftAddr("待生成");
        }
        //设置等级列表
        daoLevelVO.setList(daoLevelDetailsList);
        return daoLevelVO;
    }
}
